Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
cmake_minimum_required(VERSION 3.15)
project(farmhash LANGUAGES CXX)

include(GNUInstallDirs)

if(NOT FARMHASH_NO_BUILTIN_EXPECT)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-obvious no_builtin_expect semantics are correct but undocumented. Tracing the logic: with no_builtin_expect=ON the probe is skipped (if(NOT ON) is false), leaving FARMHASH_HAS_BUILTIN_EXPECT empty, so line 18's if(NOT FARMHASH_HAS_BUILTIN_EXPECT) is true and the macro is defined — force-disable works. With OFF (default) the probe runs and auto-detects. So OFF means "auto-detect," not "builtin is used." This ON=force / OFF=autodetect contract, plus the fact that the macro is exported PUBLIC (propagates to consumers), is worth a brief comment either here or in the .gox.

# Transcribed from farmhash/src/Makefile.am
include(CheckCXXSourceCompiles)
check_cxx_source_compiles(
"int main(int argc, char* argv[]) { return (int)__builtin_expect(0, 0); }"
FARMHASH_HAS_BUILTIN_EXPECT
)
endif()

add_library(farmhash "${FARMHASH_SRC_DIR}/src/farmhash.cc" )
target_include_directories(farmhash PRIVATE "${FARMHASH_SRC_DIR}/src")

if(NOT FARMHASH_HAS_BUILTIN_EXPECT)
target_compile_definitions(farmhash PUBLIC FARMHASH_NO_BUILTIN_EXPECT)
endif()

set_target_properties(farmhash
PROPERTIES
PUBLIC_HEADER "${FARMHASH_SRC_DIR}/src/farmhash.h"
WINDOWS_EXPORT_ALL_SYMBOLS ON
)

install(TARGETS farmhash
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import (
"os"
"path/filepath"
"slices"
"strings"
)

const consumerSource = `#include <farmhash.h>

#include <iostream>
#include <string>

int main() {
std::string aString = "Conan";
uint32_t hashResult;

hashResult = util::Hash32(aString);

std::cout << "Input string: " << aString << std::endl;
std::cout << "Generated hash: " << hashResult << std::endl;

return 0;
}
`

id "google/farmhash"

fromVer "0d859a811870d10f53a594927d0d0b97573ad06d"

defaults {
"shared": "OFF",
"fPIC": "ON",
"no_builtin_expect": "OFF",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Document the options, especially no_builtin_expect. Sibling recipes document each option at its declaration (cglm explains shared/CGLM_USE_TEST; json-c explains shared/fPIC and the static/fPIC interaction). This recipe declares shared, fPIC, and no_builtin_expect with no comments, and no_builtin_expect is the most non-obvious option in the repo. A short comment here clarifying that OFF = auto-detect (compiler probe) and ON = force-disable would match repo convention.

}

filter => {
for name, values in target.options {
if name != "shared" && name != "fPIC" && name != "no_builtin_expect" {
return false
}
for value in values {
if value != "ON" && value != "OFF" {
return false
}
}
}
return true
}

onBuild ctx => {
installDir := ctx.outputDir

cmakeLists := ctx.Proj.readFile("0d859a811870d10f53a594927d0d0b97573ad06d/CMakeLists.txt")!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Version hash literal is duplicated. The commit hash 0d859a... appears in both fromVer (line 28) and this readFile path. On a future version bump both must change in lockstep or the build silently reads the wrong CMakeLists. If the toolchain exposes a version-dir-relative path helper, prefer deriving this path from ctx rather than re-embedding the literal.

os.writeFile(filepath.join(ctx.SourceDir, "CMakeLists.txt"), cmakeLists, 0o644)!

shared := slices.contains(target.options["shared"], "ON")
fPIC := slices.contains(target.options["fPIC"], "ON")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fPIC is redundant when shared=ON. Shared libraries are always position-independent, so CMAKE_POSITION_INDEPENDENT_CODE has no effect when shared=ON. The current filter accepts all four shared/fPIC combinations, producing two functionally identical variants for shared=ON. Consider rejecting the redundant combination in filter (as mature Conan-style recipes do) to avoid building duplicate packages.

noBuiltinExpect := slices.contains(target.options["no_builtin_expect"], "ON")

c := cmake.new(ctx.SourceDir, filepath.join(ctx.SourceDir, "_build"), installDir)
c.define "FARMHASH_SRC_DIR", ctx.SourceDir
c.defineBool "BUILD_SHARED_LIBS", shared
c.defineBool "CMAKE_POSITION_INDEPENDENT_CODE", fPIC
c.defineBool "FARMHASH_NO_BUILTIN_EXPECT", noBuiltinExpect
c.configure
c.build
c.install

licenseDir := filepath.join(installDir, "licenses")
os.mkdirAll(licenseDir, 0o755)!
os.writeFile(filepath.join(licenseDir, "COPYING"), os.readFile(filepath.join(ctx.SourceDir, "COPYING"))!, 0o644)!

flags := []string{
"-I" + filepath.join(installDir, "include"),
"-L" + filepath.join(installDir, "lib"),
"-lfarmhash",
}
ctx.setMetadata strings.join(flags, " ")
}

onTest ctx => {
installDir := ctx.outputDir
testDir := filepath.join(ctx.SourceDir, "_llar_consumer")
os.mkdirAll(testDir, 0o755)!

consumer := filepath.join(testDir, "consumer.cpp")
os.writeFile(consumer, []byte(consumerSource), 0o644)!

binary := filepath.join(testDir, "consumer")
flags := []string{
"-I" + filepath.join(installDir, "include"),
consumer,
"-L" + filepath.join(installDir, "lib"),
"-lfarmhash",
"-o", binary,
}
exec "c++", flags...
lastErr!

if slices.contains(target.options["shared"], "ON") {
os.setenv("LD_LIBRARY_PATH", filepath.join(installDir, "lib"))!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

os.setenv overwrites LD_LIBRARY_PATH/DYLD_LIBRARY_PATH instead of prepending. This unconditionally replaces any existing value rather than prepending (installDir/lib:$LD_LIBRARY_PATH). For a test process this is mostly a robustness concern, but silently dropping an operator-provided library search path can change which shared objects resolve at runtime. Consider prepending to the existing value.

os.setenv("DYLD_LIBRARY_PATH", filepath.join(installDir, "lib"))!
}
exec binary
lastErr!
}
4 changes: 4 additions & 0 deletions google/farmhash/versions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"path": "google/farmhash",
"deps": {}
}
Loading