I'm in the process of putting together a small c++ project using CMake for the first time. My current project structure is
├── bch
│ ├── CMakeLists.txt
│ ├── gf
│ │ ├── CMakeLists.txt
│ │ ├── include
│ │ │ └── gf.h
│ │ └── src
│ │ └── gf.cpp
│ ├── include
│ │ └── bch.h
│ └── src
│ └── bch.cpp
├── bsc
│ ├── CMakeLists.txt
│ ├── include
│ │ └── bsc.h
│ └── src
│ └── bsc.cpp
├── CMakeLists.txt
├── .gitignore
└── main.cpp
Currently I have gf as a subdirectory of bch. The contents of bch/CMakeLists is
cmake_minimum_required(VERSION 3.17)
project(bch VERSION 0.1.0)
# Targets
add_library(bch STATIC src/bch.cpp)
# Dependant
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/gf)
target_link_libraries(bch PUBLIC gf)
# Export to dependants
target_include_directories(bch PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
I would like to take the gf CMake project and place outside of the directory path of bch. This doesn't seem to be a supported structure when using the add_subdirectory command unless I'm missing something. Generally, what would be the current "Best Practice" for accomplishing my goal of decoupling the directory structure from the dependency tree?
If you want to decouple the project from dependencies, then I would suggest splitting cmake project into two separate, exporting the dependent target and then importing it with 'find_package'. Here is quick google find for that topic:
https://visualgdb.com/tutorials/linux/cmake/find_package
[edit]
For a more general approach I suggest cmake documentation:
https://cmake.org/cmake/help/latest/command/find_package.html#command:find_package
https://cmake.org/cmake/help/latest/module/CMakePackageConfigHelpers.html
https://cmake.org/cmake/help/v3.18/command/install.html#export
The idea is:
In a dependency project to generate a '*ConfigVersion.cmake' file, install all needed files (headers, binaries and *ConfigVersion.cmake) using the 'EXPORT' in parameter the 'install' command.
In a final project use 'find_package' to import the dependency.
For bigger library projects I also suggest using namespaces to allow importing only selected parts of the library.
Related
I'm trying to use the PocketSphinx speech to text library in my project as a Git submodule. So, I added the submodule to my dependency folder and I added the following code to my MakeFile:
add_subdirectory(dependencies/pocketsphinx)
But, when I'm building the project, I'm getting an error saying that:
[build] /home/aniket/code/restapi/dependencies/pocketsphinx/src/allphone_search.c:43:10: fatal error: pocketsphinx.h: No such file or directory
[build] 43 | #include <pocketsphinx.h>
[build] | ^~~~~~~~~~~~~~~~
[build] compilation terminated.
My guess is that CMAKE cannot find the header files; but, when I build PocketSphinx alone it works fine.
I'm also using the JsonCpp library, which compiles without any problem.
My CMAKE file is:
cmake_minimum_required(VERSION 3.2.0)
project(assistant)
add_executable(${PROJECT_NAME} src/main.cpp)
add_subdirectory(dependencies/jsonpp)
add_subdirectory(dependencies/pocketsphinx)
target_include_directories(${PROJECT_NAME} PUBLIC include PUBLIC
dependencies/jsonpp/include)
target_include_directories(${PROJECT_NAME} PRIVATE include
PRIVATE dependencies/jsonpp/include)
target_link_directories(${PROJECT_NAME} PRIVATE build/lib)
target_link_libraries(${PROJECT_NAME} PRIVATE jsoncpp curl)
Here's my directory structure:
.
├── build
├── dependencies
│ ├── jsonpp
│ │ ├── cmake
│ │ ├── devtools
│ │ ├── doc
│ │ ├── example
│ │ ├── include
│ │ ├── pkg-config
│ │ ├── src
│ │ └── test
│ └── pocketsphinx
│ ├── cython
│ ├── docs
│ ├── doxygen
│ ├── examples
│ ├── gst
│ ├── include
│ ├── model
│ ├── programs
│ ├── src
│ └── test
├── include
└── src
I have a project that has multiple subdirectories and I have a unit testing framework (UnitTest++) in the following folder structure:
root_dir
├── sub_dir1
│ ├── main.cpp
│ ├── some_class.hpp
│ └── test.cpp
├── sub_dir2
│ ├── another_class.hpp
│ ├── main.cpp
│ └── test.cpp
├── UnitTest++
│ ├── libUnitTest++.a
└── makefile
I plan to have more sub_dir# in the future.
How do I use make in the root directory so that it would compile all the subdirectories?
I git clone a project called evmc in github.
I try to build the example folder in this project by cmake. But here are some errors called:
With cmake .
-- Configuring done
CMake Error at CMakeLists.txt:23 (add_executable):
Target "evmc-example" links to target "evmc::evmc_cpp" but the target was
not found. Perhaps a find_package() call is missing for an IMPORTED
target, or an ALIAS target is missing?
CMake Error at CMakeLists.txt:23 (add_executable):
Target "evmc-example" links to target "evmc::loader" but the target was not
found. Perhaps a find_package() call is missing for an IMPORTED target, or
an ALIAS target is missing?
CMake Error at CMakeLists.txt:19 (add_executable):
Target "evmc-example-static" links to target "evmc::evmc_cpp" but the
target was not found. Perhaps a find_package() call is missing for an
IMPORTED target, or an ALIAS target is missing?
CMake Error at CMakeLists.txt:19 (add_executable):
Target "evmc-example-static" links to target "evmc::evmc" but the target
was not found. Perhaps a find_package() call is missing for an IMPORTED
target, or an ALIAS target is missing?
CMake Error at CMakeLists.txt:19 (add_executable):
Target "evmc-example-static" links to target "evmc::evmc" but the target
was not found. Perhaps a find_package() call is missing for an IMPORTED
target, or an ALIAS target is missing?
CMake Error at CMakeLists.txt:16 (add_library):
Target "evmc-example-host" links to target "evmc::evmc_cpp" but the target
was not found. Perhaps a find_package() call is missing for an IMPORTED
target, or an ALIAS target is missing?
CMake Error at example_vm/CMakeLists.txt:10 (add_library):
Target "example-vm-static" links to target "evmc::evmc" but the target was
not found. Perhaps a find_package() call is missing for an IMPORTED
target, or an ALIAS target is missing?
CMake Error at example_vm/CMakeLists.txt:5 (add_library):
Target "example-vm" links to target "evmc::evmc" but the target was not
found. Perhaps a find_package() call is missing for an IMPORTED target, or
an ALIAS target is missing?
CMake Error at example_precompiles_vm/CMakeLists.txt:10 (add_library):
Target "example-precompiles-vm-static" links to target "evmc::evmc" but the
target was not found. Perhaps a find_package() call is missing for an
IMPORTED target, or an ALIAS target is missing?
CMake Error at example_precompiles_vm/CMakeLists.txt:5 (add_library):
Target "example-precompiles-vm" links to target "evmc::evmc" but the target
was not found. Perhaps a find_package() call is missing for an IMPORTED
target, or an ALIAS target is missing?
-- Generating done
CMake Generate step failed. Build files cannot be regenerated correctly.
make: *** [cmake_check_build_system] Error 1
With make
Consolidate compiler generated dependencies of target evmc-example-host
[ 14%] Built target evmc-example-host
Consolidate compiler generated dependencies of target evmc-example
[ 21%] Linking CXX executable evmc-example
ld: library not found for -levmc::loader
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [evmc-example] Error 1
make[1]: *** [CMakeFiles/evmc-example.dir/all] Error 2
make: *** [all] Error 2
Here is my CMakeLists:
# EVMC: Ethereum Client-VM Connector API.
# Copyright 2016-2019 The EVMC Authors.
# Licensed under the Apache License, Version 2.0.
cmake_minimum_required(VERSION 3.13)
set (CMAKE_C_COMPILER /usr/bin/clang)
set (CMAKE_CXX_COMPILER /usr/bin/clang++)
set (CMAKE_CXX_STANDARD 17)
include(GNUInstallDirs)
add_subdirectory(example_vm)
add_subdirectory(example_precompiles_vm)
add_library(evmc-example-host STATIC example_host.cpp)
target_link_libraries(evmc-example-host PRIVATE evmc::evmc_cpp)
add_executable(evmc-example-static example.c)
target_link_libraries(evmc-example-static PRIVATE evmc-example-host evmc::example-vm-static evmc::evmc)
target_compile_definitions(evmc-example-static PRIVATE STATICALLY_LINKED_EXAMPLE)
add_executable(evmc-example example.c)
target_link_libraries(evmc-example PRIVATE evmc-example-host evmc::loader)
include_directories(../include)
Here is my project structure:
evmc
├── AUTHORS.md
├── CHANGELOG.md
├── CMakeCache.txt
├── CMakeLists.txt
├── CNAME
├── CPackConfig.cmake
├── CPackSourceConfig.cmake
├── Cargo.lock
├── Cargo.toml
├── Doxyfile
├── LICENSE
├── Makefile
├── README.md
├── appveyor.yml
├── bindings
│ ├── go
│ ├── java
│ └── rust
├── build
│ ├── CMakeCache.txt
│ ├── CMakeFiles
│ ├── CPackConfig.cmake
│ ├── CPackSourceConfig.cmake
│ ├── Makefile
│ ├── cmake_install.cmake
│ ├── evmcConfig.cmake
│ ├── evmcConfigVersion.cmake
│ └── lib
├── circle.yml
├── cmake
│ ├── Config.cmake.in
│ ├── EVMC.cmake
│ ├── Hunter
│ └── cable
├── cmake_install.cmake
├── codecov.yml
├── docs
│ ├── EVMC.md
│ ├── Host_Guide.md
│ ├── VM_Guide.md
│ ├── VM_Tester.md
│ └── custom.dox
├── evmcConfig.cmake
├── evmcConfigVersion.cmake
├── examples
│ ├── CMakeCache.txt
│ ├── CMakeFiles
│ ├── CMakeLists.txt
│ ├── Makefile
│ ├── build
│ ├── cmake_install.cmake
│ ├── example-rust-vm
│ ├── example.c
│ ├── example_host.cpp
│ ├── example_host.h
│ ├── example_precompiles_vm
│ ├── example_vm
│ ├── libevmc-example-host.a
│ ├── use_evmc_in_cmake
│ └── use_instructions_in_cmake
├── go.mod
├── include
│ └── evmc
├── lib
│ ├── CMakeFiles
│ ├── CMakeLists.txt
│ ├── Makefile
│ ├── cmake_install.cmake
│ ├── hex
│ ├── instructions
│ ├── loader
│ └── mocked_host
├── target
│ ├── CACHEDIR.TAG
│ └── debug
├── test
│ ├── CMakeLists.txt
│ ├── cmake_package
│ ├── compilation
│ ├── examples
│ ├── gomod
│ ├── tools
│ ├── unittests
│ └── vmtester
└── tools
├── CMakeLists.txt
├── commands
├── evmc
├── utils
└── vmtester
I have upgraded any tools I use in this project: clang, cmake...
But it still can't run correctly, what should I do?
This happened to me because the path I used for the library was incorrect, it was not pointing to the directory that contained the CMakeLists.txt.
I was including cpr using FetchContent in my top level CMakeLists.txt and setting FETCHCONTENT_SOURCEDIR_CPR to the level above accidentally.
I had the source for cpr inside cpr/cpr-master but had just set it to cpr.
To answer more generally it means that the path to evmc is probably incorrect.
I'm fairly new to webpack and I'm trying to understand what's the proper way to include my assets folder into the dist folder using webpack (or one of its plugins).
This is the structure of my project:
├── package.json
├── webpack.config.js
├── src
│ ├── index.html
│ ├── app.js
│ ├── components
│ │ ├── ...
│ ├── assets
│ │ ├── factory.png
│ │ ├── factory_white.png
I managed to solve my own issue by reading around about copy-webpack-plugin
I wanted to compile my project using command:
ocamlfind ocamlopt -package ocamlnet -package batteries -package unix -linkpkg oauth.ml
but I'm getting following error:
ocamlfind: Package `ocamlnet' not found
make: *** [oauth.cmi] Error 2
After some research on this problem I have read that there may be problem with packages installed via opam and packages installed before opam installation (in this case with ocamlfind) so I tried to check that and get stuck because ocamlfind is installed via opam. Does anybody know what may I try to do to solve that problem?
$ which ocamlfind
/home/user/.opam/4.00.1/bin/ocamlfind
$ opam list
Installed packages for 4.00.1:
[...]
ocamlfind 1.4.0 A library manager for OCaml
[...]
Thanks in advance.
Do a:
eval $(opam config env)
That should fix the problem.
# Edit 1:
If it still does not work remove the dir
/home/user/.opam/4.00.1
and try it again.
I'm making answer because of limit in comments and partial results I've made. Here is the result of 'grep -r 'ocamlnet' *' at '~/.opam' directory: http://pastebin.com/8cJqMXDY by looking at lines 1-90 we may conclude that there is actually no ocamlnet library at all (or I'm looking for it in wrong place - but as I wrote in comment everything were installed using opam - I'd be glad to hear some opinions on this subject). These suspicions may be partially confirmed in two ways:
in fact in lines 1-90 we've all binaries of ocamlnet components (http://projects.camlcity.org/projects/dl/ocamlnet-3.7.3/doc/html-main/index.html)
lines 90-* doesn't seem like something other than some files needed to manage this package using opam. E.g.
~/.opam/repo/default/packages/ocamlnet$ tree -r .
.
├── ocamlnet.3.7.3
│ ├── url
│ ├── opam
│ ├── files
│ │ └── ocamlnet.install
│ └── descr
├── ocamlnet.3.6.5
│ ├── url
│ ├── opam
│ ├── files
│ │ ├── ocamlnet.install
│ │ ├── netpop.patch
│ │ ├── nethttpd_types.patch
│ │ └── cloexec.patch
│ └── descr
├── ocamlnet.3.6.3
│ ├── url
│ ├── opam
│ ├── files
│ │ └── ocamlnet.install
│ └── descr
├── ocamlnet.3.6.0
│ ├── url
│ ├── opam
│ ├── files
│ │ ├── ocamlnet-ocaml4.diff
│ │ └── ocamlnet.install
│ └── descr
├── ocamlnet.3.5.1
│ ├── url
│ ├── opam
│ ├── files
│ │ └── ocamlnet.install
│ └── descr
└── ocamlnet.3.2.1
├── url
├── opam
├── files
│ └── ocamlnet.install
└── descr
I do not have a sufficiently large knowledge to go into it deeper but it looks for me like that ocamlnet become just a shortcut for a few another packages used by opam. Especially that after changing
-package ocamlnet
to exact module which I'm using
-package netstring
everything has compiled fine. I'm still open to any other solutions or explenations for the curious case of ocamlnet package (and Michael's hints) B).