android cmakelist add multi source file? - android-ndk

I write NDK project using Android Studio & CMakelist.
But when I want to include lots cpp/c files to CMakelists.txt , I can not find a easy way to do it gently.
I need your help.
Here is my code's file tree sample:
Cmakelists.txt
src
|__main
|__cpp
|___a.cpp // cpp file
|___a.h
|___aa.c // c file
|___...
|___dirA // a dir
|__b.c // also has c file
|__b.h
|__d.cpp // and cpp file
|__...
|___dirB // another dir
|__xxx.c
|__...
In my Cmakelist, I used
file(GLOB cpp_srcs "src/main/cpp/*.cpp")
This seems only include the fist directory layer's cpp files , NOT include c files, and the sub dir's cpp/c files .
Any way to make it ? The dir is too deep, I don't want to add cpp/c files manually.

You can try:
file(GLOB_RECURSE cpp_srcs "src/main/cpp/*.c" "src/main/cpp/*.cpp")
or maybe:
file(GLOB_RECURSE cpp_srcs_c "src/main/cpp/*.c")
file(GLOB_RECURSE cpp_srcs_cpp "src/main/cpp/*.cpp")
set(cpp_srcs ${cpp_srcs_c} ${cpp_srcs_cpp})
I'm not sure if the first pattern works and I can't test now, but the second should do it.

Related

Purify build using scons

I need to do purify build using SCons. Normally in nmake we would do
Nmake install -purify_7.0.1.0-008
How to do the same in SCons? Do I need to add any change in SConstruct file?
You'll need to prefix SHCC,CC, SHCXX, CXX, SHLINK, LINK with purify, and likely add the path to your purify binary to env['ENV']['PATH']
You'll need to do this anywhere (in the main SConstruct, all SConscripts, and if you have any code in site_scons) which creates an Environment() to use.
If you create one Enviroment() and that gets exported to your SConscripts where it's then env.Clone()'d, then you'd only have to change it in the initial env=Environment()
Here's an example (not tested):
env=Environment() # this is your existing code
for v in ['SHCC','CC','SHCXX','CXX','LINK','SHLINK']:
orig_value = env.subst('$%s'%v)
env['v'] = "purify "+ orig_value
print("Changing $%s from :\n%s\nto:\n%s",v, orig_value, env['v'])

New header file not showed in Project Mode in Android Studio 3.1.1

I'm trying to learn a bit of Android development.
I've started a new project for a simple hello world and it works fine.
The project is essentially the default one + one more header file in the cpp folder,
However I can't see such .cpp in the project mode, can anyone suggest how to fix this?
(See picture below).
I've attempted to change some setting in File > Project Structure but it doesn't seem to make any difference.
Maybe worth noticing that the header file isn't listed in the CMakeLists.txt at all.
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/native-lib.cpp )
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${log-lib} )
According to the android doc:
Known Issue: Android Studio currently shows you only the header files that have matching source files—even if you specify other headers in your CMake build script. See Issue #38068472
This means you need a pair filename.h and filename.cpp, you modify your CMakeLists.txt accordingly. The header file will be shown in project mode if it has a corresponding .cpp with the same name.
Reference:
https://developer.android.com/studio/projects/add-native-code

how to compile in vc++ without .dsw workspace file?

I downloaded a source code from codeproject.com
In the zip file only .cpp files and .hpp files were present but no .dsw (vc++ work space) file.
how to compile the files in vc++.
source code link: http://www.codeproject.com/Articles/13852/BasicExcel-A-Class-to-Read-and-Write-to-Microsoft
As far as I know, vc++ requires a dsw. That said, you can easily create one by creating a project + workspace and add import all the files into the project.
Unless the code requires special compile options (unlikely if it comes without a project file), this should work fine.
When you compile in VisualC++ cl.exe is executed in order to compile a s program.
So a way to compile that does not require dsw file might be running compilation in command line. This is an example for a source file main.cpp:
call vsvars32.bat && cl /MD /Od /EHsc /GR /Zi /Oy- main.cpp
On my computer the full path to vsvars32.bat is
C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\Tools\vsvars32.bat
dsw is an ancient format, and is replaced by .sln and .vcxproj files. What I would suggest would be File -> New -> Project from existing code, browse to the directory with the cpp/hpp files and let Visual Studio create the project with default compiler switches - so you won't have to run cl.exe from the command line as suggested here.
That being said, the chances of circa-2006 c++ code to work on IDEs 4 versions later are small. You will almost certainly have to understand and fix the code - or find a more recent one that does what you need.

How to include an additional CMakeLists.txt

Say we have a command call foo in CMakeLists.txt which is in folder /A.
foo is defined in antother CMakeLists.txt which is in folder /B.
How can one reference to /B/CMakeLists.txt from within /A/CMakeLists.txt in order to call foo?
I tried to set search paths to /B/CMakeLists.txt via:
CMAKE_INCLUDE_PATH
CMAKE_MODULE_PATH
CMAKE_SOURCE_DIR
but none of them worked.
CMake still complaines Unknown CMake command "foo".
That can be done with include, here's some simple example:
Content of A/CMakeLists.txt
function(foo)
message(STATUS "heya")
endfunction()
Content of B/CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
include(${CMAKE_CURRENT_SOURCE_DIR}/../A/CMakeLists.txt)
foo()
Now, including another CMakeLists.txt will also run everything in that file, so you may want to avoid doing that if there are targets in B/CMakeLists.txt
If you can modify your code, it would be better to define your functions in a "top level" CMakeLists.txt before calling add_subdirectory.
If this files just contains functions definitions you should not call it CMakeLists.txt, but some_adequate_name.cmake
Than you can include it where you need those functions definitions using include.

Automatically add all files in a folder to a target using CMake?

I am considering switching a cross platform project from separate build management systems in Visual C++, XCode and makefiles to CMake.
One essential feature I need is to add automatically all files in a directory to a target. While this is easy to do with make, it is not easily doable with Visual C++ and XCode (correct me if I am wrong). Is it possible to do it in directly in CMake? How?
As of CMake 3.1+ the developers strongly discourage users from using file(GLOB or file(GLOB_RECURSE to collect lists of source files.
Note: We do not recommend using GLOB to collect a list of source files from your source tree. If no CMakeLists.txt file changes when a source is added or removed then the generated build system cannot know when to ask CMake to regenerate. The CONFIGURE_DEPENDS flag may not work reliably on all generators, or if a new generator is added in the future that cannot support it, projects using it will be stuck. Even if CONFIGURE_DEPENDS works reliably, there is still a cost to perform the check on every rebuild.
See the documentation here.
There are two goods answers ([1], [2]) here on SO detailing the reasons to manually list source files.
It is possible. E.g. with file(GLOB:
cmake_minimum_required(VERSION 2.8)
file(GLOB helloworld_SRC
"*.h"
"*.cpp"
)
add_executable(helloworld ${helloworld_SRC})
Note that this requires manual re-running of cmake if a source file is added or removed, since the generated build system does not know when to ask CMake to regenerate, and doing it at every build would increase the build time.
As of CMake 3.12, you can pass the CONFIGURE_DEPENDS flag to file(GLOB to automatically check and reset the file lists any time the build is invoked. You would write:
cmake_minimum_required(VERSION 3.12)
file(GLOB helloworld_SRC CONFIGURE_DEPENDS "*.h" "*.cpp")
This at least lets you avoid manually re-running CMake every time a file is added.
The answer by Kleist certainly works, but there is an important caveat:
When you write a Makefile manually, you might generate a SRCS variable using a function to select all .cpp and .h files. If a source file is later added, re-running make will include it.
However, CMake (with a command like file(GLOB ...)) will explicitly generate a file list and place it in the auto-generated Makefile. If you have a new source file, you will need to re-generate the Makefile by re-running cmake.
edit: No need to remove the Makefile.
Extension for #Kleist answer:
Since CMake 3.12 additional option CONFIGURE_DEPENDS is supported by commands file(GLOB) and file(GLOB_RECURSE). With this option there is no needs to manually re-run CMake after addition/deletion of a source file in the directory - CMake will be re-run automatically on next building the project.
However, the option CONFIGURE_DEPENDS implies that corresponding directory will be re-checked every time building is requested, so build process would consume more time than without CONFIGURE_DEPENDS.
Even with CONFIGURE_DEPENDS option available CMake documentation still does not recommend using file(GLOB) or file(GLOB_RECURSE) for collect the sources.
To use Visual Studio project hierarchy inside Clion with cmake:
cmake_minimum_required(VERSION 3.17)
project(MyProject)
set(CMAKE_CXX_STANDARD 17)
file(GLOB APP_SOURCES */*.cpp)
foreach (testsourcefile ${APP_SOURCES})
get_filename_component(testname ${testsourcefile} NAME_WLE)
get_filename_component(dirname ${testsourcefile} DIRECTORY)
file(GLOB dir_src CONFIGURE_DEPENDS
"${dirname}/*.h"
"${dirname}/*.cpp"
)
message("${testname}.cpp | ${dir_src}")
add_executable("${testname}.cpp" ${dir_src})
endforeach (testsourcefile ${APP_SOURCES})
So Why not use powershell to create the list of source files for you. Take a look at this script
param (
[Parameter(Mandatory=$True)]
[string]$root
)
if (-not (Test-Path -Path $root)) {
throw "Error directory does not exist"
}
#get the full path of the root
$rootDir = get-item -Path $root
$fp=$rootDir.FullName;
$files = Get-ChildItem -Path $root -Recurse -File |
Where-Object { ".cpp",".cxx",".cc",".h" -contains $_.Extension} |
Foreach {$_.FullName.replace("${fp}\","").replace("\","/")}
$CMakeExpr = "set(SOURCES "
foreach($file in $files){
$CMakeExpr+= """$file"" " ;
}
$CMakeExpr+=")"
return $CMakeExpr;
Suppose you have a folder with this structure
C:\Workspace\A
--a.cpp
C:\Workspace\B
--b.cpp
Now save this file as "generateSourceList.ps1" for example, and run the script as
~>./generateSourceList.ps1 -root "C:\Workspace" > out.txt
out.txt file will contain
set(SOURCE "A/a.cpp" "B/b.cpp")

Resources