For a project I am autogenerating multiple Fortran source files using add_custom_command. To my knowledge this results in CMake creating a GENERATED source file that I can add to a target such as a library or executable. However, since the file does not exist at CMake compile time CMake cannot use the source_group command to group these generated files for the IDE (Visual Studio).
Is there another way to achieve the same result as source_group that I cannot find? For example when using CMake with Qt you can set the AUTOGEN_SOURCE_GROUP to change the source group for the automoc and autorcc generated files.
Example.
# Creates a command to generate the 'a.f90' file using 'mytool.exe' and 'a.f90.in'.
add_custom_command(
OUTPUT a.f90
COMMAND mytool.exe a.f90.in
DEPENDS a.f90.in
)
add_executable(example a.f90 b.f90 c.f90) # Where b.f90 and c.f90 are not generated
source_group("Source Files/Not Generated" FILES "b.f90 c.f90")
source_group("Source Files/Generated" FILES a.f90) # Does nothing
This results in the following visual studio filters,
Source Files
|- Non Generated Files
|- b.f90
|- c.f90
|- a.f90
instead of
Source Files
|- Non Generated Files
|- b.f90
|- c.f90
|- Generated Files
|- a.f90
To help others who might be trying the same thing. Here's my workaround. I couldn't find a way to group autogenerated files using add_custom_command. This leaves a possible solution. If you are fine with not having the files autogenerated when your code is compiled you may instead use the execute_process command. With execute_process the command will be run when CMake creates the build tree instead of when you compile your source code. Since the files will already exist may be added as normal source files and can be grouped using source_group.
Example
# Generates 'a.f90'
execute_process(COMMAND mytool.exe a.f90.in ${CMAKE_CURRENT_BINARY_DIR}/a.f90)
add_executable(main "${CMAKE_CURRENT_BINARY_DIR}/a.f90" b.f90 c.f90)
source_group("Source Files/Not Generated" FILES "b.f90 c.f90")
source_group("Source Files/Generated" FILES a.f90)
With this the visual studio filters look like
Source Files
|- Generated
|- a.f90
|- Not Generated
|- b.f90
|- c.f90
I've been trying to migrate a project from VS to CMake, but I'm not sure my project structure is quite fit to a simple migration:
project/
|- CMakeLists.txt
|- build/
|- (cmake stuff)
|- src/
|- main.cpp
|- tests.cpp // also contains a main()
|- class1.hpp
|- class1.cpp
|- class2.hpp
|- class2.cpp
|- ...
|- included/
| - (external libs)
My CMakeLists.txt attempt so far has been:
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
set(CMAKE_LEGACY_CYGWIN_WIN32 0)
add_executable(webnectar src/main.cpp
src/test.cpp)
enable_testing()
add_test(tests project)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/included)
But I get linking errors with my own classes., I don't understand why.
In several other SO questions I've seen people using file GLOBs to include all sources from a subfolder, which I guess would be a solution. Still, I wish I understood why include_directories is not enough and why (if it would work) file GLOB is OK.
Also, using file GLOB would mess with my build because both test.cpp and main.cpp have a main function.
Although it would look like a different matter (for a different question), please consider this question as more general in the sense of how could I fix all these issues with either a CMake syntax or with a more suitable file structure.
Regarding include_directories This directive corresponds to -I compiler flag and allows compiler to find header files, i.e. those which are included in #include ....
You should mention all your source files in the arguments of add_executable. That's unavoidable.
You could form the complete list of sources with FILE(GLOB..):
FILE(GLOB webnectar_SOURCES RELATIVE src/ *.cpp)
and then use it in add_executable(webnectar ${webnectar_SOURCES}).
However, this would not be the best and safest option, because it contains a significant flaw. The list of files is formed during the "configuring" stage of the build process (e.g. cmake -D<....> -D<.....> .) and then it's never rebuilt until CMake-related files (CMakeLists.txt, CMakeCache.txt and so on) somehow change. So if you first run cmake... and then add a new file, it won't be noticed, and Makefiles won't be regenerated.
Additionally, if some extra files (e.g. left after an interrupted merge) fit the mask you will get some quite unexpected results.
So it's safer to form and maintain an explicit list of sources, that is,
set(webnectar_SOURCES
src/main.cpp
src/class1.cpp
src/class2.cpp
...
)
and then use it in add_executable(webnectar ${webnectar_SOURCES}). The name of variable can be any but some IDEs like KDevelop prefer a standard naming <artifact>_SOURCES, so they can mantain the list automatically for you (or at least try to maintain :) )
I am having trouble getting Intellij to recognize the generated source code from antlr4. Any reference to the generated code appears as errors, code completion doesn't work, etc.
I am using maven and the antlr4-maven-plugin to generate the code.
My code, referencing the generated code compiles and builds fine under maven.
The generated code is under /target/generated-sources/antlr4, which is what Intellij expects.
I have tried the usual fixes such as reimport maven projects, update folders, invalidate cache, etc. None of it seems to work.
Anyone seen this before?
Is there a way to point to the generated sources directly within Intellij?
The problem
target/generated-sources/antlr4 is not automatically marked as source dir, instead its direct subdir com.example is. Intellij Idea fails to detect proper package for classes inside target/generated-sources/antlr4/com.example.
The cause
The source file *.g4 is in src/main/antlr4/com.example, but it actually it should be src/main/antlr4/com/example. Note the /. You probably forgot to mark src/main/antlr4 as source dir in Idea, and when you thought you are creating package structure, you actually just created single dir called com.example.
The fix
Mark src/main/antlr4 as source dir, create proper directory structure src/main/antlr4/com/example. Rebuild.
Alternative fix
Go to Project Structure - Modules - Source Folders and find the target/generated-sources/antlr4/com.example - click Edit properties and set Package prefix to com.example.
Different but related problem here
My issue was somewhat similar to #spilymp's:
I was putting the *.g4 files directly in src/main/antlr4:
.
├── src/
| └── main/
| ├── antlr/
| | ├── Main.g4
| | └── imported.g4
| └── java/
| └── com/
| └── test/
| └── Test.java
which led to source being generated in default package. I changed the package structure to match that of java:
.
├── src/
| └── main/
| ├── antlr/
| | ├── com/
| | | └── test/
| | | └── Main.g4
| | └── imports/
| | └── imported.g4
| └── java/
| └── com/
| └── test/
| └── Test.java
(Note that imports need to go directly in src/main/antlr4/imports)
After this I just run the antlr4 goal from the maven menu ([Module] > Plugins > antlr4 > antlr4:antlr4), which generated the sources in the default location (target/generated-sources/antlr4), where they were already marked with blue, generated-sources icon by Intellij, and MainParser can now be imported!
It turns out that my fiddling with preferences caused this issue. If anyone else has this problem:
As v0rl0n mentioned, first make sure the gen folder is listed as a source. Go to Module Settings -> Modules -> Sources.
Look to the right for the blue Source Folders. Ensure your generated source folders are listed (they should have a [generated] flag on the row).
If your generated source directory is listed there, and they are still not being recognized, go to Preferences -> File Types. Look in the Ignore files and folders field. Make sure you don't have anything listed that will match for your generated sources directory.
In my case, I had added target to this list, which caused my problem, and was a real pain to find.
I had what I think may have been a similar issue. I am new to IntelliJ, so I am guessing to some extent.
Is the gen folder in your project brown (i.e. a resource) or blue (source code)?
I could not get my project to recognize generated code until I managed to get the gen folder registered as one containing source code.
Sorry to say you may need to fiddle with it - I cannot recall how I did it - but all was well after I changed this.
Steps that worked for me:
Open Maven Projects in right tab
Right click on the module that contained my antlr code
Click Generate Source and Update Folders
I had a similar problem. Intellij found my generated code in the java folder but not in a subfolder of java. I solved it by putting my grammar files (*.g4) into a package (com.test):
.
├── src/
| └── main/
| ├── antlr/
| | └── com.test/
| | └── Test.g4
| └── java/
| └── test/
| └── Test.java
└── target/
└── generated-sources/
└── antlr/
└── com.test/
├── TestBaseListener.java
└── ...
The easiest way to solve this issue is to Right-Click the gen directory and choose Mark Directory as -> Sources Root
I'm using cmake to build my project in C++. Assume I have the following directories on my Source folder
Source
|_Dir1
| |_Class.cpp
| |_Class.hpp
|
|_Dir2
|_Main.cpp
In Dir1 there's a class with its header and implementation files (Class.cpp and Class.hpp).
In Dir2 there's the main application which uses the class in Dir1
What is the good way to tell the CMakeLists in Dir2 to build the executable with Dir1/Class.cpp file?
EDIT: To be more specific, I want to define that the source file for Class.cpp has to be used in Dir1's CMakeLists.txt, and not in Dir2's. Doing it the other way feels plain wrong to me and it's hard to use, so if there's a reason they're enforcing me to do this some clarification on the topic would be nice.
What I'm currently doing is hard-coding the Class.cpp file location in Dir2/CMakeLists.txt but that just doesn't scale when I've got a bunch of classes interacting together.
Supposed you have a single CMakeLists.txt file at the Source directory, you'll create two variables using different file() commands
file(GLOB Dir1_Sources RELATIVE "Dir1" "*.cpp")
file(GLOB Dir2_Sources RELATIVE "Dir2" "*.cpp")
and add both sets generated by the file() commands to your target's source list:
add_executable(MyProgram ${Dir1_Sources} ${Dir2_Sources})
Alternatively you can place a CMakeLists.txt file under Dir1 and Dir2 (Main) looking as follows
Source
|
|_ CMakeLists.txt
| > project(MyProgram)
| > cmake_minimum_required(VERSION 3.8)
| > add_subdirectory("Dir1")
| > add_subdirectory("Dir2")
|
|_ Dir1
| |_ CMakeLists.txt
| > file(GLOB Sources "*.cpp")
| > add_library(Dir1 STATIC ${Sources})
|_ Dir2
|_ CMakeLists.txt
> file(GLOB Sources "*.cpp")
> add_executable(MyProgram ${Sources})
> target_link_libraries(MyProgram Dir1)
to add subdirectories as further (static) libraries linked to your main target.
in my project when I build it via the standard:
mvn clean package
I can see subversion specific files when inspecting the generated jar file. If I unzip the jar the content looks like:
myApp.jar
|- _svn <- subversion files
|- com <- my classes
|- META-INF
|- some.xml <- some configuration
...
I would like to exclude the _svn folder from all my generated jars. Any tips?
Thanks