Include from upper layer of files - meson-build

I've got main project structure in 1 folder, and units tests closed in another folder(2 different meson instances). In unit tests i need to include one file from main project(element to be tested). I dont want to specify relative path as i want to be portable between other programmers.
How can i instruct meson to first go back from current folder and then look through application files if there is file i'm looking for? I want to make it that way so any change in code can be tested right away without any copying or modifications.
C:\Users\User1\Project\application
C:\Users\User1\Project\unittests
I need to be able to see files from application while beeing currently on unittests

Declare project dependency at top level meson.build like
project_dep = declare_dependency(include_directories: inc_dir, sources: srcs, dependencies:[...])
Make sure that your main is not in the sources. In test level meson.build
include project_dep like this:
unit_tests_exec = executable('UnitTests', gtest_srcs,
dependencies :[gtest_dep, gmock_dep, project_dep])
You can check how I organized project using meson for Tdd session here:
https://github.com/elvisoric/tdd_session

Related

Hierarchical CMake project that also works when building an "inner" (non-root) project

Suppose I have a hierarchical CMake project, composed of n different projects:
CMakeLists.txt
proj-1/CMakeLists.txt
proj-2/CMakeLists.txt
(...)
proj-n/CMakeLists.txt
Evidently there'll be the source files for each project as well.
I'd ensure all commands of interest are added to the root CMakeLists.txt file -- say, CMAKE_CXX_STANDARD, enable_testing(), add_compile_options(), etc. If I understand correctly, whichever options are included in the root CMakeLists.txt file are also applied to all children CMakeLists.txt file -- please correct me if I'm wrong, since I'm counting on this behavior. The root CMakeLists.txt also contains an add_subdirectory(proj-X) statement for each X = 1, ..., n.
Anyway. Suppose, for some reason, that I would like to build only one of the proj-X folders, say proj-1. Maybe the build is broken in one of the other projects, or maybe I need to fix a bug on proj-1, it doesn't depend on the other projects, and it would take forever to build all projects.
The point is: I would like to run cmake on proj-1/CMakeLists.txt rather than on the root CMakeLists.txt file, and yet I would like to ensure that proj-1 is built in exactly the same way it would be build, had I run cmake on the root CMakeLists.txt file. This is an issue since the root CMakeLists.txt contains statements that the children CMakeLists.txt should "inherit" from in the regular situation where it's built from the root, and yet in this scenario I'm building directly from proj-1/CMakeLists.txt (the root CMakeLists.txt file doesn't come into the picture in this scenario.)
One possibility, as I understand, would be to copy all options from the root CMakeLists.txt file to every other proj-X/CMakeLists.txt file. Of course, this is a hack and a maintenance nightmare, but I suppose it would work.
Are there other possible solutions? Can I, say, create a file containing all the common options and save it to the root, and then do the CMake equivalent of #include within each of the proj-X/CMakeLists.txt files? Would there be an issue due to running the same commands twice (once on the root CMakeLists.txt and another on the proj-X/CMakeLists.txt file, when starting the build from the root)?
You may need to rework some of your CMakeLists.txt files.
I would recommend watching Daniel Pfeifer's Effective CMake talk at CPPcon (slides available here).
The gist of it is that all of your projects should provide everything they need in order to be build or compiled, in essence build requirements and usage requirements. To achieve this in a maintainable and scalable way you have to move away from variables and setting global options (add_compile_options, include_directories, etc) and instead focus on targets (target_compile_options, target_include_directories, etc).
So, in your case proj-1/CMakeLists.txt will provide one target (let's call it proj::proj1) that sets the proper PUBLIC and INTERFACE options (by options I mean needed compiler features, dependencies, include directories, etc).
An abstract example:
project(proj1)
add_library(proj1 src.cpp)
# This are private include files, whoever uses this library does not need them
target_include_directories(proj1 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
# These are public, needed both by this target and by whoever uses it.
target_include_directories(proj1 PUBLIC
# This is used when building the target
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/public/include>
# This is used when the target is installed
$<INSTALL_INTERFACE:include>)
# Instead of asking directly for a language standard we ask for a compiler feature. We make this public so whoever depends on this target knows they also need this feature.
target_compile_features(proj1 PUBLIC cxx_strong_enums)
# As above, but this is needed only by this target during the build.
target_compile_features(proe1 PRIVATE cxx_lambdas)
# Add an alias, users can use target_link_libraries(target PRIVATE|PUBLIC proj::proj1) to add this target as a dependency (this will propagate all the PUBLIC include paths, compile options, compile features, dependencies, etc.
add_library(proj::proj1 ALIAS proj1)
This is highly abstract, it depends on what you're actually doing in your build scripts, it's hard to give a better explanation than Daniel Pfeifer, so I recommend watching his talk or at least reading the slides. It will make your build scripts a lot easier to write, read, and use.
Another great resource is this site.

CMake: Remove header dependency

Is there any way to make CMake "forget" about a file in the dependency tree? My original problem (to avoid the XY situation) is the following: I want to timestamp the build of a set of tools which have complicated dependencies among them and to other tools. Right now, I want to use a pure timestamp, but later I might want add some info from the repository (SVN). Whatever system I end up implementing needs to have the following characteristics (my "X"):
No unnecessary rebuilding: the executables should not be rebuilt on every make if the only change would be the timestamp.
Update on any change: if any tool is going to be rebuilt or relinked, either by changes to its code or to one of its dependencies, the timestamp needs to be updated.
My current solution goes along the lines of creating a custom command+target that invokes CMake at make time (so the command calls CMake itself with -P script.cmake) to generate a timestamp.h file. The main files of my tools would include that file, and the projects would depend on the target so that it gets rebuilt first.
However, this has its drawbacks: if I do update the timestamp file on every call to make, then CMake's dependency scanner would know about that file even if I do not list it as an explicit dependency of my tools. Thus, every make would trigger at least a recompilation of the respective "main" files and the corresponding relink. With tens of tools, this means slowing down the build when I may be working on just two or three of them at once.
So, I was thinking that my solution would be to somehow make CMake forget about that file when building its dependency tree for the "main" file of each tool. I would keep the dependency on the custom target that does depend on the file, so that it would be regenerated first on each call to make. However, the build tool would not consider that file as relevant to determine whether it is necessary to actually rebuild each individual tool. Thus, tools only with other changes would be rebuilt (satisfying my first criterion), and any change that causes a rebuild of a tool would obviously use the version just generated (fulfilling the second criterion).
To my chagrin, I have not found a way to make the dependency scanner forget about this file, so my solution cannot be put to use. How would I go about doing such a thing? Is it even possible, or is it completely the wrong way to go about this? I am using CMake 3.4, and my code is currently C++, but I would like a solution that did not rely on C/C++ specifics, since I have a different project (written in Fortran) in which I would also like to have build timestamping.
I've had almost the same problem than you are. Simply solved by pushing the timestamp header file into standalone target containing only this header generator command. After that you have several choices:
1.. Exclude that project from the build by the IDE you are using. For example, for the Visual Studio you can do it by several ways:
1.1. Project->Project Dependencies...->uncheck project with that header (not always works: Error while removing project dependency in VS2010)
1.2. Build->Configuration Manager...->uncheck project with that header
2.. Create an environment variable and use the condition with that variable around the add_dependencies command in the CMakeLists.txt file.
3.. Generate 2 standalone solutions through the cmake generator with included and with excluded add_dependencies in the CMakeLists.txt file.
I've used particulary [1.2]. When i need build and debug, then i uncheck the dependecy. By default, dependecy always checked, so there is no problem to miss timestamp build for a build server.
Note:
The timestamp header will be included in all projects you want to include that header (for example, through the add_library and add_executable) and you still can observe it in the IDE under a project item menu even if a project depends on the timestamp project indirectly. This is useful if you don't want to search for the timestamp project with the header to open it from there and want to open it from any project which has included that header.
So, in case of removing the timestamp header from the add_library or add_executable you won't have that opportunity.

Adding a two new phases to an Xcode framework project

I am building a project on Github written in Objective-C. It resolves MAC addresses down to manufacturer details. The lookup table is currently stored as text file manuf.txt (from the Wireshark project), which is parsed at run-time, which is costly. I would prefer to compile this down to archived objects at build-time, and load that instead.
I would like to amend the build phases such that I:
Build a simple compiler
Run the compiler, parsing manuf.txt and outputting archived objects
Build the framework
Copy the archived objects into the framwork
I am looking for wisdom on how to achieve steps 1 and 2 using Xcode v7.3 as Xcode provides only a Copy Files phase or a Run Script phase. An example of other projects achieving similar goals would be inspiring.
I suspect that what you are asking is possible, but tricky. The reason is that you will need to write a bunch of class files and then dynamically add them to the project.
Firstly you will need to employ a run script phase to run various tools from the command line to parse your file and generate a number of class files from it. I would suggest looking into various templating engines. For example appledoc uses moustache templates to generate API documentation files. You could use the same technique to generate header and implementation files.
Next, rather than generating archived objects an trying to import into a framework. I think you may be better off generating raw source code, adding it to a project and compiling into a framework. Probably simpler in the long run.
To automatically include the generated code I would look into (which means I haven't actually tried this :-) adding a folder reference to the project rather than an Xcode group. Folder references are an option in the 'Add files to ...' dialog.
Folder references refer to a directory and automatically add the entire contents of that directory to a project. So you can use one to point to the directory where you have generated the source code. This is a much better option than trying to manipulate the project or injecting things into an established framework.
I would prefer to parse the file at runtime. After launch you can look for an already existing output, otherwise parse it one time.
However, I have to do something similar at Objective-Cloud. I simply added a run script build phase and put the compiler call into it.

In cmake, what is a "project"?

This question is about the project command and, by extension, what the concept of a project means in cmake. I genuinely don't understand what a project is, and how it differs from a target (which I do understand, I think).
I had a look at the cmake documentation for the project command, and it says that the project command does this:
Set a name, version, and enable languages for the entire project.
It should go without saying that using the word project to define project is less than helpful.
Nowhere on the page does it seem to explain what a project actually is (it goes through some of the things the command does, but doesn't say whether that list is exclusive or not). The cmake.org examples take us through a basic build setup, and while it uses the project keyword it also doesn't explain what it does or means, at least not as far as I can tell.
What is a project? And what does the project command do?
A project logically groups a number of targets (that is, libraries, executables and custom build steps) into a self-contained collection that can be built on its own.
In practice that means, if you have a project command in a CMakeLists.txt, you should be able to run CMake from that file and the generator should produce something that is buildable. In most codebases, you will only have a single project per build.
Note however that you may nest multiple projects. A top-level project may include a subdirectory which is in turn another self-contained project. In this case, the project command introduces additional scoping for certain values. For example, the PROJECT_BINARY_DIR variable will always point to the root binary directory of the current project. Compare this with CMAKE_BINARY_DIR, which always points to the binary directory of the top-level project. Also note that certain generators may generate additional files for projects. For example, the Visual Studio generators will create a .sln solution file for each subproject.
Use sub-projects if your codebase is very complex and you need users to be able to build certain components in isolation. This gives you a very powerful mechanism for structuring the build system. Due to the increased coding and maintenance overhead required to make the several sub-projects truly self-contained, I would advise to only go down that road if you have a real use case for it. Splitting the codebase into different targets should always be the preferred mechanism for structuring the build, while sub-projects should be reserved for those rare cases where you really need to make a subset of targets self-contained.

How to add to project additional files not intended to be compiled?

I would like to add into project some files that shouldn't be compiled. I mean mainly text files with for example notes, concepts, comments etc.
I realized that it is possible only at module level. But it is not very convenient. I'd rather prefer to keep them on project level. Is it possible in any way?
And if not:
I have another idea: to create special module, name it for example "other_stuff", do not create src directory and put files there. Is it ok? I'm afraid of potential compilation problems when one of modules is artificial, with no sources but still has sdk assigned (it is probably impossible to leave module without sdk assigned).
While generating artifacts you can add any file into your artifact. Also, in modules you can have folders not declared as source, and they will not be compiled.